package main;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import packing.BoxNode;
import packing.BoxShape;
import packing.Container;
import packing.Box;
import packing.State;
import utility.ConnectMySQL;
import utility.FileTool;

public class Brutforce {
	private double BastevaluationScore = 0;
	private int countOfBox = 0;
	private List<Object> stateList = new ArrayList<Object>();
	private State main_state;
	private String BastevaluationScoreText;
	private Container container = Container.getInstance();
	private int size;
	private int index = 1;
	private int maxVolumn = 0, bastStateIndex = 0;
	private List<State> baseStateList = new ArrayList<State>();
	private State bastState;
	private ConnectMySQL connect = new ConnectMySQL();

	public void solve(State state) throws Exception {
		connect.run();
		main_state = state;
		eval_solution(generateBoxList(main_state));
		FileWriter file;
		try {
			int tmp2 = connect.getCount("state");
			file = new FileWriter("TestFiles/result.txt");
			for (int i = 1; i <= tmp2; i++) {
				State state2 = (State) connect.getObject("state", i);
				String s = state2.getState(size);
				System.out.println(i+" "+state2.getBoxLine());
				if (state2.checkUseArea()&&state.calculateX(size)&&state.calculateY(size)&&state.calculateZ(size)) {
					String str = (index++) + " " + s + "/ "
							+ state2.getBoxLine() + "\n";
					file.write(str);
					int max = state2.getVolume();
					if (maxVolumn == max) {
						baseStateList.add(state2);
					}
					if (maxVolumn < max) {
						bastStateIndex = index - 1;
						maxVolumn = max;
						bastState = state2;
						baseStateList.clear();
						baseStateList.add(state2);
					}
				}

			}
			file.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		FileTool.writeReport(container, bastState, bastStateIndex);
		FileTool.writeBoxPlace(container, baseStateList);
	}

	private void SortStateList() {
		for (int i = 0; i < stateList.size(); i++) {
			for (int j = i + 1; j < stateList.size(); j++) {
				if (((BoxNode) stateList.get(i)).getPoint() < ((BoxNode) stateList
						.get(j)).getPoint()) {
					State tmp = (State) stateList.get(i);
					stateList.set(i, stateList.get(j));
					stateList.set(j, tmp);
				}
			}
		}
	}

	public void createBoxPlace(State state) {
		FileWriter file;
		String str = "";
		try {
			file = new FileWriter("boxplaces.txt");
			str += container.getLength() + "\n" + container.getWidth() + "\n"
					+ container.getHeight() + "\n";
			str += state.getStrBoxplaces();
			file.write(str);
			file.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public List<Object> generateBoxList(State state) throws Exception {
		List<Box> stateBoxList = state.getBoxInputList();
		for (Box box : stateBoxList) {
			connect.setJavaObject(box);
			connect.saveObject("box");
			if (box.getPriceBox() > 0) {
				for (int i = 1; i <= box.getPriceBox(); i++) {
					box.setId(box.getId() + "_" + i);
					connect.setJavaObject(box);
					connect.saveObject("box");
				}
			}
			if (box.isxR()) {
				box.xRotate();
				connect.setJavaObject(box);
				connect.saveObject("box");
				if (box.getPriceBox() > 0) {
					for (int i = 1; i <= box.getPriceBox(); i++) {
						box.setId(box.getId() + "_" + i);
						connect.setJavaObject(box);
						connect.saveObject("box");
					}
				}
			}
			if (box.isyR()) {
				box.yRotate();
				connect.setJavaObject(box);
				connect.saveObject("box");
				if (box.getPriceBox() > 0) {
					for (int i = 1; i <= box.getPriceBox(); i++) {
						box.setId(box.getId() + "_" + i);
						connect.setJavaObject(box);
						connect.saveObject("box");
					}
				}
			}
			if (box.iszR()) {
				box.zRotate();
				connect.setJavaObject(box);
				connect.saveObject("box");
				if (box.getPriceBox() > 0) {
					for (int i = 1; i <= box.getPriceBox(); i++) {
						box.setId(box.getId() + "_" + i);
						connect.setJavaObject(box);
						connect.saveObject("box");
					}
				}
			}
		}
		return connect.getObjectAll("box");
	}

	public void eval_solution(List<Object> box) throws Exception {
		countOfBox++;
		size = box.size();
		for (int b = 0; b < size; b++) {
			State state = new State();
			Box[][][] con = container.createContianner(size);
			con[0][0][0] = (Box) box.get(b);
			state.addState(box.get(b), 0, 0, 0);
			connect.setJavaObject(state);
			connect.saveObject("state");
			if (countOfBox < size) {
				eval_recursive(con, state, box);
				countOfBox--;
			}

		}
	}

	public void eval_recursive(Box[][][] con, State state, List<Object> box)
			throws Exception {
		countOfBox++;
		for (int b = 0; b < size; b++) {
			boolean chk = true;
			for (BoxNode nb : state.getAllBox()) {
				if (nb.box.getId().equalsIgnoreCase(((Box) box.get(b)).getId())) {
					chk = false;
					break;
				}
			}
			if (!chk)
				continue;
			for (int x = 0; x < size; x++) {
				for (int y = 0; y < size; y++) {
					for (int z = 0; z < size; z++) {
						Box[][][] con2 = container.createContianner(size);
						copyArray(con, con2);
						State state2 = new State();
						state2.addAllBox(state.getAllBox());
						if (con2[x][y][z] == null) {
							con2[x][y][z] = (Box) box.get(b);
							state2.addState(box.get(b), x, y, z);
							if (state2.checkNextBox()) {
								connect.setJavaObject(state2);
								connect.saveObject("state");
								if (countOfBox < size) {
									eval_recursive(con2, state2, box);
									countOfBox--;
								}
							} else {
								break;
							}
						}
					}
				}
			}
		}
	}

	public void evaluationScore() {
		System.out.println();
		for (Object s : stateList) {
			System.out.println(((State) s).evaluate());
			if (BastevaluationScore < ((State) s).getEvaluationScore()) {
				BastevaluationScore = ((State) s).getEvaluationScore();
				BastevaluationScoreText = ((State) s).evaluate();
			}
		}
		System.out.println("Bast Evaluation Score\n" + BastevaluationScoreText);
	}

	public void copyArray(Box[][][] con, Box[][][] con2) {
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				for (int z = 0; z < size; z++) {
					con2[x][y][z] = con[x][y][z];
				}
			}
		}
	}
}
